/**
    Copyright (c) 2010 yakiimo02
    Distributed under the New BSD License.
    See included license.txt or http://www.yakiimo3d.com/NewBSDLicense.txt
**/

#pragma once

#include "MandelbrotCS.h"
#include "MandelbrotCPU.h"
#include "DataBufferDX11.h"

enum MandelbrotMode 
{
    MANDELBROT_MODE_CPU,                    // use cpu
    MANDELBROT_MODE_CS                        // use compute shader
};

/**
    @brief  Manages the CPU and CS Mandelbrot implementations.
    @author yakiimo02
    @date    2010/01/31
*/
class MandelbrotMgr
{
public:
    MandelbrotMgr();
    ~MandelbrotMgr();

    HRESULT OnCreateDevice( ID3D11Device* pd3dDevice );
    HRESULT OnResizedSwapChain( ID3D11Device* pd3dDevice, const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc );
    void    OnFrameRender( ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3dImmediateContext,
                                  double fTime, float fElapsedTime, void* pUserContext );
    void    OnDestroyDevice();
    
    LRESULT HandleMessages( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );

    void    TranslateCenter( const D3DXVECTOR2& vDeltaCenter );
    void    ZoomScale( const float fDeltaScale );
    
    void    SetnMaxIterations( int nMaxIterations );

    inline void SetMode( const MandelbrotMode mode ) { m_mode = mode; }

    inline D3DXVECTOR2                GetvCenter() const;
    inline float                    GetfZoomScale() const;
    inline const ConstantBuf*        GetpConstantBuf() const;
    inline MandelbrotMode            GetMode() const { return m_mode; }
    inline DataBufferDX11*            GetpDataBufferDX11() { return &m_dataBufferDX11; }
    inline int                        GetnMaxIterations();

protected:
    MandelbrotCPU        m_cpu;                    // cpu
    MandelbrotCS        m_cs;                    // compute shader
    MandelbrotMode        m_mode;                    // cpu or computeshader
    DataBufferDX11        m_dataBufferDX11;        // uav, srv stuff
};

extern MandelbrotMgr    g_mandelbrotMgr;


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/**
*/
D3DXVECTOR2 MandelbrotMgr::GetvCenter() const 
{ 
    if( m_mode == MANDELBROT_MODE_CPU ) {
        return m_cpu.GetvCenter(); 
    }
    else if( m_mode == MANDELBROT_MODE_CS ) {
        return m_cs.GetvCenter();
    }
    else { assert( 0 ); }
    return D3DXVECTOR2();
}

/**
*/
float MandelbrotMgr::GetfZoomScale() const 
{ 
    if( m_mode == MANDELBROT_MODE_CPU ) {
        return m_cpu.GetfZoomScale();
    }
    else if( m_mode == MANDELBROT_MODE_CS ) {
        return m_cs.GetfZoomScale();
    }
    else { assert( 0 ); }
    return 0.0f;
}

/**
*/
const ConstantBuf* MandelbrotMgr::GetpConstantBuf() const
{
    if( m_mode == MANDELBROT_MODE_CPU ) {
        return m_cpu.GetpConstantBuf();
    }
    else if( m_mode == MANDELBROT_MODE_CS ) {
        return m_cs.GetpConstantBuf();
    }
    else { assert( 0 ); }
    return NULL;
}

/**
*/
int    MandelbrotMgr::GetnMaxIterations()
{
    if( m_mode == MANDELBROT_MODE_CPU ) {
        return m_cpu.GetnMaxIterations();
    }
    else if( m_mode == MANDELBROT_MODE_CS ) {
        return m_cs.GetnMaxIterations();
    }
    else { assert( 0 ); }
    return NULL;
}